<?php

use Service\AlipayOpenPlatform\AopFactory;

class ControllerExtensionOauthAlipayPc extends Controller {

    const EXTENSION_GROUP = 'oauth';

    const EXTENSION_TYPE = 'alipay_pc';

    const SETTING_CODE = self::EXTENSION_GROUP . '_' . self::EXTENSION_TYPE;

	public function loginAction()
    {
        $this->load->language('extension/oauth/alipay_pc');

        $setting = $this->model_setting_setting->getSetting(self::SETTING_CODE);

        return [
            'type'  => 'alipay_pc',
            'title' => $this->language->get('text_title'),
            'action' => 'https://openauth.alipay.com/oauth2/publicAppAuthorize.htm?' . http_build_query([
                'scope'        => 'auth_user',
                'app_id'       => $this->config->get('oauth_alipay_pc_app_id'),
                'state'        => 'pc_oauth_login',
                'redirect_uri' => $this->url->link('account/login/oauthCallback') . '&type=alipay_pc',
                    // 在外面拼接 . '&type=wechat_pc' 防止 & 被 link 方法转成 &amp;
            ]),
            'sort_order' => $this->config->get('oauth_alipay_pc_sort_order'),
            'icon' => image_resize($setting[self::SETTING_CODE. '_icon']),
        ];
	}

    /**
     * 使用 支付宝登录 回调
     *
     * @example
     *  回调地址示例
     *  http://example.com/doc/toAuthPage.html?app_id=2014101500013658&source=alipay_wallet&scope=auth_user&auth_code=ca34ea491e7146cc87d25fca24c4cD11
        参数
        * $request = [
            'route'       => 'account/login/alipayCallback',
            'state'       => 'init',
            'app_id'      => '2016081501751560',
            'source'      => 'alipay_wallet',
            'userOutputs' => 'auth_user',
            'scope'       => 'auth_user',
            'auth_code'   => '7fb750d515cd4eed8d7cefab088aUF06',
        ]
     *
     * @throws Exception
     */
    public function callback()
    {
        $oauthUser = $this->getOauthUser();
//        $oauthUser = $this->queryOauthUser();

        $customer_id = (int) $oauthUser['customer_id'];
        if ($customer_id) {
            $this->customer->loginByCustomerId($customer_id); // 改成 customer

            return $this->url->link('account/login/oauthSuccess');
        } else {
            $query = http_build_query([
                'oauth_type'    => 'alipay_pc',
                'oauth_user_id' => $oauthUser['alipay_user_id'],
            ]);

            return $this->url->link('account/register', $query);
        }
    }

    /**
     * @return bool
     *
     * @throws Exception
     */
    public function bindCustomer()
    {
        /** @var ModelExtensionOauthAlipayUser $modelAlipayUser */
        $modelAlipayUser = $this->loadModel('extension/oauth/alipay_user');

        $modelAlipayUser->bindCustomer($this->customer->getId(), $this->requestGet('oauth_user_id'));

        return true;
    }

    /**
     * @param $user_info
     *
     * @return array
     * @throws Exception
     */
    protected function updateOrCreateUser($user_info)
    {
        /** @var ModelExtensionOauthAlipayUser $modelUser */
        $modelUser = $this->loadModel('extension/oauth/alipay_user');

        $user = $modelUser->updateOrCreateUserInfo($user_info);

        return $user;
    }

    /**
     * @return array
     * @throws Exception
     */
    protected function getOauthUser()
    {
        $aop = (new AopFactory)->productionAop($this->config);
        $access_token = $this->queryAccessToken($aop);
        $user_info = $this->queryUserInfo($aop, $access_token);
        $user_data = $this->normalizeUserData($user_info);
        $alipay_user = $this->updateOrCreateUser($user_data);

        return $alipay_user;
    }

    public function queryOauthUser()
    {
//        query from laravel api
    }

    /**
     * @param AopClient $aop
     *
     * @return null
     * @throws Exception
     */
    protected function queryAccessToken(AopClient $aop)
    {
        $oauth = new AlipaySystemOauthTokenRequest();
        $oauth->setCode($this->requestAny('auth_code'));
        $oauth->setGrantType("authorization_code");
//die($this->requestAny('auth_code'));
        /**
         * $res = (object) [
         * "alipay_system_oauth_token_response" => [
         * "access_token"   => "authusrBe57af8e3346246af96740cafca31aF06",
         * "alipay_user_id" => "20881075931959181964981560611106",
         * "expires_in"     => 1296000,
         * "re_expires_in"  => 2592000,
         * "refresh_token"  => "authusrBaecf10cc7a394492910db5f8648f8C06",
         * "user_id"        => "2088102081601069",
         * ],
         * "sign"  => "XgdFCnUD...",
         * ];
         */
        $res = $aop->execute($oauth);
        $access_token = isset($res->alipay_system_oauth_token_response->access_token)
            ? $res->alipay_system_oauth_token_response->access_token
            : null;

        if (! $access_token) {
            $this->jsonError('授权发生错误');
        }

        return $access_token;
}

    /**
     * @param AopClient $aop
     * @param string $access_token
     *
     * @return mixed
     * @throws Exception
     */
    protected function queryUserInfo(AopClient $aop, $access_token)
    {
        $userInfoRequest = new AlipayUserInfoShareRequest();
        /**
         * $user_info = [
         * 'alipay_user_info_share_response' =>
         * [
         * 'code'                 => '10000',
         * 'msg'                  => 'Success',
         * 'avatar'               => 'https://tfs.alipayobjects.com/images/partner/T1VCNpXj4cXXXXXXXX',
         * 'city'                 => '广州市',
         * 'gender'               => 'm',
         * 'is_certified'         => 'T',
         * 'is_student_certified' => 'F',
         * 'nick_name'            => '智翔',
         * 'province'             => '广东省',
         * 'user_id'              => '2088102081601069',
         * 'user_status'          => 'T',
         * 'user_type'            => '2',
         * ],
         * 'sign'                            => 'MuUIX...',
         * ];
         */
        $user_info = $aop->execute($userInfoRequest, $access_token);
        $user_id = isset($user_info->alipay_user_info_share_response->user_id)
            ? $user_info->alipay_user_info_share_response->user_id
            : null;

        if (! $user_id) {
            $this->jsonError('无法获取授权用户信息');
        }

        return (array) $user_info->alipay_user_info_share_response;
}

    /**
     * @param $user_info
     *
     * @return array
     */
    protected function normalizeUserData($user_info): array
    {
        $user_data = array_only($user_info, [
            'avatar', 'city', 'gender', 'is_certified', 'is_student_certified',
            'nick_name', 'province', 'user_id', 'user_status', 'user_type',
        ]);

        return $user_data;
}
}